import java.awt.event.*;
import javax.swing.*;
import javax.media.opengl.*;
import javax.media.opengl.awt.*;  
import javax.media.opengl.glu.*;
import com.jogamp.opengl.util.gl2.GLUT; 

public class ObjectModel  extends glskeleton
                          implements GLEventListener, KeyListener 
                          {

    private GLUT glut;
    
    float rotX = 0;
    float rotY = 0;
    float rotZ = 0;
    
    
    public static void main(String[] args) {
    
    
        final javax.media.opengl.awt.GLCanvas canvas = new javax.media.opengl.awt.GLCanvas();
        ObjectModel demo = new ObjectModel();
        demo.setCanvas(canvas);
        canvas.addGLEventListener(demo);
        demo.setDefaultListeners(demo);
        
        JFrame frame = new JFrame("Object Model");
        frame.setSize(500, 500+26);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        frame.getContentPane().add(canvas);
        frame.setVisible(true);
        canvas.requestFocusInWindow();
    }
    
    /*
     * Initialize material property, light source, lighting model, and depth
     * buffer.
     */
    public void init(GLAutoDrawable drawable) {
        GL2 gl = drawable.getGL().getGL2();
        glut = new GLUT();


        gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        
        gl.glShadeModel(GL2.GL_SMOOTH);
        gl.glEnable(GL2.GL_DEPTH_TEST);   
        
        if (true) {
            float[] light_position = { -5.0f, 10.0f, 5.0f, 0.0f };
            float[] lightAmbient = {0.25f, 0.25f, 0.25f, 1.0f};        
            float[] lightDiffuse = {1f, 1f, 1f, 1.0f};   
                       
            gl.glEnable(GL2.GL_LIGHTING);
            gl.glEnable(GL2.GL_LIGHT0);
            gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_POSITION, light_position, 0);
            gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_DIFFUSE, lightDiffuse, 0);
            gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_AMBIENT, lightAmbient, 0);

               
        } 
        
    }
    
    
    public void display(GLAutoDrawable drawable) {
        GL2 gl = drawable.getGL().getGL2();
        
        gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
        gl.glColor3f(1,0,0);
        
        float mat_diffuse[] = { 0.5f, 1.0f, 0.5f, 1.0f };
        float mat_ambient[] = { 0.5f, 1.0f, 0.5f, 1.0f }; 
        gl.glMaterialfv(GL.GL_FRONT, GL2.GL_DIFFUSE, mat_diffuse, 0);
        gl.glMaterialfv(GL.GL_FRONT, GL2.GL_AMBIENT, mat_ambient, 0); 

        gl.glPushMatrix();
        gl.glRotatef(rotX,1,0,0);
        gl.glRotatef(rotY,0,1,0);
        gl.glRotatef(rotZ,0,0,1);
        
        // a triangle
        /*     
        gl.glBegin(GL2.GL_POLYGON);
        gl.glVertex3f(-1,0,0);
        gl.glVertex3f(1,0,0);
        gl.glVertex3f(0,1,0);
        gl.glEnd();        
        */

        // spiral stair
//        for (int i = 0; i < 20; i++) {
//        	gl.glPushMatrix();
//            gl.glRotatef(i*10,0,1,0);         	
//            gl.glTranslatef(1,.1f*i,0);        	
//            gl.glScalef(0.5f,0.1f,0.25f);             
//            glut.glutSolidCube(1.0f);
//            gl.glPopMatrix();     
//            
//        	gl.glPushMatrix();
//            gl.glRotatef(180+i*10,0,1,0);         	
//            gl.glTranslatef(1,.1f*i,0);        	
//            gl.glScalef(0.5f,0.1f,0.25f);             
//            glut.glutSolidCube(1.0f);
//            gl.glPopMatrix();                
//        }

        // Make it fit the screen.
        gl.glScalef(.5f, .5f, .5f);
        gl.glTranslatef(0, 1, 0);
       
        // Tippy Top
        for(int i = 0; i < 8; i++){

        	// Inner Building
        	gl.glPushMatrix();
        	gl.glRotatef(45*i,0,1,0);         
        	gl.glTranslatef(0,0f,0.375f); 
            gl.glBegin(GL2.GL_POLYGON);
            gl.glVertex3f(-0.16f,0,0);
            gl.glVertex3f(0.16f,0,0);
            gl.glVertex3f(0.16f,.75f,0);
            gl.glVertex3f(-0.16f,.75f,0);
            gl.glEnd();            
            gl.glPopMatrix();

            // Pillars
        	gl.glPushMatrix();
        	gl.glRotatef(45*i,0,1,0);         
        	gl.glTranslatef(.28f,.75f,0.69f); 
        	gl.glRotatef(90,1,0,0);         
            glut.glutSolidCylinder(.075, .75, 36, 36);
            gl.glPopMatrix();
            
            gl.glPushMatrix();
        	gl.glRotatef(i*45,0,1,0);         	
        	gl.glTranslatef(0,.75f,0.766f);    
        	gl.glRotatef(-60,1,0,0);    

        	// Pointy Tip
            gl.glBegin(GL2.GL_POLYGON);
            gl.glVertex3f(-0.32f,0,0);
            gl.glVertex3f(0.32f,0,0);
            gl.glVertex3f(0,.89f,0);
            gl.glEnd();             
            
            // Support Things
        	gl.glRotatef(60,1,0,0);    
            gl.glTranslatef(0,-0.05f,-.05f);
            gl.glScalef(0.64f,0.1f,0.1f);  
            glut.glutSolidCube(1.0f);
        	gl.glPopMatrix();
        }
        
        //Skirt
        for(int i = 0; i < 8; i++){
        	gl.glPushMatrix();

        	gl.glRotatef(45*i,0,1,0);     
        	if(i%2 == 0){
        		// Small Under Support Things
                gl.glPushMatrix();
                gl.glTranslatef(0,-0.6f,1.375f);
                gl.glScalef(0.825f,0.25f,0.1f);  
                glut.glutSolidCube(1.0f);
                gl.glPopMatrix();
                
                // Small Trapezoidal Things
                gl.glPushMatrix();    
            	gl.glTranslatef(0,0,0.85f); 
            	gl.glRotatef(135,1,0,0);     
            	gl.glRotatef(-7,1,0,0);    
        		gl.glBegin(GL2.GL_POLYGON);
        		gl.glVertex3f(-0.36f,0,0);
        		gl.glVertex3f(0.36f,0,0);
        		gl.glVertex3f(0.46f,.835f,0);
        		gl.glVertex3f(-0.46f,.835f,0);
        		gl.glEnd();    
                gl.glPopMatrix();
        	}
        	else{
        		// Big Under Support Things
                gl.glPushMatrix();    
                gl.glTranslatef(0,-0.6f,1.25f);
                gl.glScalef(1.45f,0.25f,0.1f);  
                glut.glutSolidCube(1.0f);
                gl.glPopMatrix();

                // Big Trapezoidal Things
                gl.glPushMatrix();    
            	gl.glTranslatef(0,0,0.85f); 
            	gl.glRotatef(135,1,0,0);     
        		gl.glBegin(GL2.GL_POLYGON);
        		gl.glVertex3f(-0.35f,0,0);
        		gl.glVertex3f(0.35f,0,0);
        		gl.glVertex3f(0.75f,.75f,0);
        		gl.glVertex3f(-0.75f,.75f,0);
        		gl.glEnd(); 
                gl.glPopMatrix();
        	}
            
            gl.glPopMatrix();
        }
        
        //Basey base
        for(int i = 0; i < 4; i++){
            gl.glPushMatrix();    
            gl.glRotated(45, 0, 1, 0);
        	gl.glRotatef(90*i,0,1,0);  
        	
            gl.glPushMatrix();    
            gl.glTranslatef(0,-0.75f,1.25f);
            gl.glScalef(1.45f,0.15f,0.1f);  
            glut.glutSolidCube(1.0f);
            gl.glPopMatrix();

            gl.glPushMatrix();    
            gl.glTranslatef(0,-2.6f,1.25f);
            gl.glScalef(2.59f,0.5f,0.1f);  
            glut.glutSolidCube(1.0f);
            gl.glPopMatrix();

            gl.glPushMatrix();    
            gl.glTranslatef(.6f,-1.5f,1.175f);
            gl.glRotatef(90, 0, 0, 1);
            gl.glScalef(1.75f,0.25f,0.25f);  
            glut.glutSolidCube(1.0f);
            gl.glPopMatrix();

            gl.glPushMatrix();    
            gl.glTranslatef(-.6f,-1.5f,1.175f);
            gl.glRotatef(90, 0, 0, 1);
            gl.glScalef(1.75f,0.25f,0.25f);  
            glut.glutSolidCube(1.0f);
            gl.glPopMatrix();

            gl.glPushMatrix();    
            gl.glTranslatef(.95f,-1f,1.25f);
            gl.glRotatef(135, 0, 0, 1);
            gl.glScalef(.75f,0.15f,0.1f);  
            glut.glutSolidCube(1.0f);
            gl.glPopMatrix();

            gl.glPushMatrix();    
            gl.glTranslatef(-.95f,-1f,1.25f);
            gl.glRotatef(-135, 0, 0, 1);
            gl.glScalef(.75f,0.15f,0.1f);  
            glut.glutSolidCube(1.0f);
            gl.glPopMatrix();
            
            gl.glPushMatrix();    
            gl.glTranslatef(-.95f,-.6f,.95f);
            gl.glRotatef(-45, 0, 1, 0);
            gl.glRotatef(145, 1, 0, 0);
            gl.glBegin(GL2.GL_POLYGON);
            gl.glVertex3f(-0.4f,0,0);
            gl.glVertex3f(0.4f,0,0);
            gl.glVertex3f(0,.89f,0);
            gl.glEnd();             
            gl.glPopMatrix();

            //Glass Face Things
            gl.glPushMatrix();    
            gl.glTranslatef(0,-2.6f,1.15f);
            gl.glBegin(GL2.GL_POLYGON);
            gl.glVertex3f(-1.155f,0,0);
            gl.glVertex3f(1.155f,0,0);
            gl.glVertex3f(1.155f,1.4f,0);
            gl.glVertex3f(.75f,2.0f,0);
            gl.glVertex3f(-.75f,2.0f,0);
            gl.glVertex3f(-1.155f,1.4f,0);
            gl.glEnd();             
            gl.glPopMatrix();

            gl.glPopMatrix();
        }
        
        // conventional (non-spiral) stairs
//        
//        for (int i = 0; i < 10; i++) {
//        	gl.glPushMatrix();
//            gl.glTranslatef(1-.1f*i,.1f*i,0);
//            gl.glRotatef(90,0,1,0);
//            gl.glScalef(0.5f,0.1f,0.25f);             
//            glut.glutSolidCube(1.0f);
//            gl.glPopMatrix();  
//        }
        

        

        gl.glPopMatrix();          
        gl.glFlush();
    }
    
    public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h) {
        System.out.println(w+" "+h);
        GL2 gl = drawable.getGL().getGL2();
        
        gl.glViewport(0, 0, w, h);
        gl.glMatrixMode(GL2.GL_PROJECTION);
        gl.glLoadIdentity();
        if (w <= h) 
            gl.glOrtho(-1.5, 1.5, -1.5 * (float) h / (float) w, 1.5 * (float) h / (float) w,
                    -10.0, 10.0);
        else
            gl.glOrtho(-1.5 * (float) w / (float) h, 
                    1.5 * (float) w / (float) h, 
                    -1.5, 1.5, -10.0, 10.0);
        gl.glMatrixMode(GL2.GL_MODELVIEW);
        gl.glLoadIdentity();
    }
    
    public void displayChanged(GLAutoDrawable drawable, boolean modeChanged,
                               boolean deviceChanged) {
    }
    
    public void keyTyped(KeyEvent key) {
    }
    
    public void dispose(javax.media.opengl.GLAutoDrawable dr) {
    }        
    
    public void keyPressed(KeyEvent key) {
        switch (key.getKeyCode()) {
            case KeyEvent.VK_ESCAPE:
                super.runExit();
                break;
            case KeyEvent.VK_LEFT:
                rotY -= 3;
                refresh();
                break;  
            case KeyEvent.VK_RIGHT:
                rotY += 3;
                refresh();
                break;  
            case KeyEvent.VK_UP:
                rotX -= 3;
                refresh();              
                break;  
            case KeyEvent.VK_DOWN:
                rotX += 3;
                refresh();
                break;  
            case KeyEvent.VK_PAGE_UP:
                rotZ += 3;
                refresh();
                break;
            case KeyEvent.VK_PAGE_DOWN:
                rotZ -= 3;
                refresh();
                break;                                                                                             
            default:
                System.out.println(key.getKeyCode());
                break;
        }
    }
    
    public void keyReleased(KeyEvent key) {
    }
    
}

/*
gl.glBegin(GL2.GL_LINE_STRIP);
for (double i = 0; i < 2; i += 0.1) {
    
    gl.glVertex3f(1*(float)Math.cos(0+i*10),
    		      1*(float)Math.sin(0+i*10),0);
    
}
*/